﻿using LeRenard.ScriptWars.Model.Entities;
using LeRenard.ScriptWars.Model.Scripting.Definitions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace LeRenard.ScriptWars.Model.Scripting
{
    /// <summary>
    /// Implementation of a concrete operation.
    /// </summary>
    public sealed class Operation : IOperation
    {
        #region Properties
        /// <summary>
        /// Gets the line number the operation is defined on.
        /// </summary>
        public int LineNumber { get { return _lineNumber; } }
        private readonly int _lineNumber;

        /// <summary>
        /// Gets the associated definition of the operation.
        /// </summary>
        public IOperationDefinition Definition { get { return _definition; } }
        private readonly IOperationDefinition _definition;

        /// <summary>
        /// Gets the parameters of the parameter, if any.
        /// </summary>
        public IEnumerable<IOperationParameter> Parameters { get { return new ReadOnlyCollection<IOperationParameter>(_parameters); } }
        private readonly IList<IOperationParameter> _parameters;        
        #endregion

        #region Construction
        /// <summary>
        /// Creates a new <see cref="Operation"/> object.
        /// </summary>
        /// <param name="lineNumber">The line number.</param>
        /// <param name="definition">The <see cref="IOperationDefinition"/> attached.</param>
        /// <param name="parameters">The <see cref="IOperationParameter"/>s attached.</param>
        public Operation(int lineNumber, IOperationDefinition definition, IEnumerable<IOperationParameter> parameters)
        {            
            ThrowIf.Null(() => definition);
            ThrowIf.Null(() => parameters);            

            _lineNumber = lineNumber;
            _definition = definition;
            _parameters = parameters.ToList();            
        }
        #endregion

        #region Methods
        /// <summary>
        /// Executes the operation.
        /// </summary>        
        public void Execute(IEntity entity, IAlgorithmCycler algorithmCycler, IGame game)
        {
            Definition.ExecutionMethod(entity, algorithmCycler, game, this);
        }
        #endregion
    }
}
